package cn.smile.business.core.impl;

import cn.smile.bean.dto.core.DicInfoDTO;
import cn.smile.bean.dto.core.ShareUserDTO;
import cn.smile.bean.dto.core.SysUserDTO;
import cn.smile.bean.entity.core.ShareRelation;
import cn.smile.bean.form.core.share.QueryShareForm;
import cn.smile.bean.form.core.share.UpdateBindDicForm;
import cn.smile.bean.form.core.user.QueryUserForm;
import cn.smile.business.core.IDicInfoService;
import cn.smile.business.core.IShareRelationService;
import cn.smile.business.core.ISysUserService;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.constant.RedisKeyConstant;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.commons.enums.core.DicParentEnum;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import cn.smile.repository.core.ShareRelationMapper;
import cn.smile.utils.BeanCopy;
import cn.smile.utils.PasswordUtil;
import cn.smile.utils.RedisUtil;
import cn.smile.utils.UserUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
public class ShareRelationServiceImpl extends BaseServiceImpl<ShareRelationMapper, ShareRelation> implements IShareRelationService {
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ISysUserService userService;
    @Resource
    private IDicInfoService dicService;

    @Override
    public String getShareCode() {
        log.info("[ShareRelationServiceImpl].[getShareCode] ------> 生成用户共享绑定码 Start");
        String shareCode = PasswordUtil.randomNum(NumberConstant.SIX);
        String userId = UserUtil.getUserInfo().getId();
        String key = String.format(RedisKeyConstant.USER_SHARE_CODE_KEY, shareCode);
        redisUtil.set(key, userId, RedisKeyConstant.USER_SHARE_CODE_TIMEOUT);
        log.info("[ShareRelationServiceImpl].[getShareCode] ------> 生成用户共享绑定码 End, shareCode = {}", shareCode);
        return shareCode;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean bindShare(String shareCode) {
        log.info("[ShareRelationServiceImpl].[bindShare] ------> 绑定共享关系 Start, shareCode = {}", shareCode);
        if (ObjectUtils.isEmpty(shareCode)) {
            throw new BusinessException(MyResponseCode.SHARE_CODE_ERROR);
        }
        String myId = UserUtil.getUserInfo().getId();
        String key = String.format(RedisKeyConstant.USER_SHARE_CODE_KEY, shareCode);
        Object bucket = redisUtil.get(key);
        log.info("bucket");
        if (ObjectUtils.isEmpty(bucket)) {
            throw new BusinessException(MyResponseCode.SHARE_CODE_ERROR);
        }
        String bindUserId = String.valueOf(bucket);
        if (myId.equals(bindUserId)) {
            throw new BusinessException(MyResponseCode.SHARE_BIND_MY_ERROR);
        }
        ShareRelation oldEntity = baseMapper.selectOne(new QueryWrapper<ShareRelation>().lambda().eq(ShareRelation::getUserId, myId).eq(ShareRelation::getShareUserId, bindUserId));
        if (!ObjectUtils.isEmpty(oldEntity)) {
            throw new BusinessException(MyResponseCode.SHARE_BIND_EXIST_ERROR);
        }
        ShareRelation entity = new ShareRelation();
        entity.setUserId(myId);
        entity.setShareUserId(bindUserId);
        boolean flag = super.create(entity);
        if (flag) {
            ShareRelation shareEntity = new ShareRelation();
            shareEntity.setUserId(bindUserId);
            shareEntity.setShareUserId(myId);
            super.create(shareEntity);
            redisUtil.del(key);
        }
        log.info("[ShareRelationServiceImpl].[bindShare] ------> 绑定共享关系 End, flag = {}", flag);
        return flag;
    }

    @Override
    public IPage<ShareUserDTO> getSharePage(QueryShareForm form) {
        log.info("[ShareRelationServiceImpl].[getSharePage] ------> 分页查询共享用户 Start, form = {}", JSON.toJSONString(form));
        List<ShareRelation> shareList = baseMapper.selectList(new QueryWrapper<ShareRelation>().lambda().eq(ShareRelation::getUserId, UserUtil.getUserInfo().getId()).eq(ShareRelation::getDeleted, Boolean.FALSE));
        List<String> shareUserIds = Lists.newArrayList();
        Map<String, Integer> relDicMap = Maps.newHashMap();
        if (!CollectionUtils.isEmpty(shareList)) {
            shareList.forEach(share -> {
                shareUserIds.add(share.getShareUserId());
                relDicMap.put(share.getShareUserId(), share.getRelationDicValue());
            });
        } else {
            shareUserIds.add(UUID.randomUUID().toString());
        }
        QueryUserForm userForm = BeanCopy.copyBean(form, QueryUserForm.class);
        userForm.setIds(shareUserIds);
        IPage<SysUserDTO> userPage = userService.queryPage(userForm);
        IPage<ShareUserDTO> shareUserPage = BeanCopy.copyPage(userPage, ShareUserDTO.class);
        this.setDetail(shareUserPage.getRecords(), relDicMap);
        log.info("[ShareRelationServiceImpl].[getSharePage] ------> 分页查询共享用户 End");
        return shareUserPage;
    }

    @Override
    public List<ShareUserDTO> getShareList(QueryShareForm form) {
        log.info("[ShareRelationServiceImpl].[getShareList] ------> 列表查询共享用户 Start, form = {}", JSON.toJSONString(form));
        form.setSize(Integer.MAX_VALUE);
        form.setPage(NumberConstant.ONE);
        IPage<ShareUserDTO> sharePage = this.getSharePage(form);
        List<ShareUserDTO> shareList = Lists.newArrayList();
        if (!ObjectUtils.isEmpty(sharePage) && !CollectionUtils.isEmpty(sharePage.getRecords())) {
            shareList.addAll(sharePage.getRecords());
        }
        log.info("[ShareRelationServiceImpl].[getShareList] ------> 列表查询共享用户 End");
        return shareList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delBind(String shareUserId) {
        log.info("[ShareRelationServiceImpl].[delBind] ------> 删除绑定共享关系 Start, shareUserId = {}", shareUserId);
        if (ObjectUtils.isEmpty(shareUserId)) {
            throw new BusinessException(MyResponseCode.SHARE_USER_ID_ERROR);
        }
        String userId = UserUtil.getUserInfo().getId();
        ShareRelation entity = baseMapper.selectOne(new QueryWrapper<ShareRelation>().lambda().eq(ShareRelation::getUserId, userId).eq(ShareRelation::getShareUserId, shareUserId));
        boolean flag = super.delById(entity.getId());
        if (flag) {
            entity = baseMapper.selectOne(new QueryWrapper<ShareRelation>().lambda().eq(ShareRelation::getUserId, shareUserId).eq(ShareRelation::getShareUserId, userId));
            super.delById(entity.getId());
        }
        log.info("[ShareRelationServiceImpl].[delBind] ------> 删除绑定共享关系 End, flag = {}", flag);
        return flag;
    }

    @Override
    public Boolean updateRelationDic(UpdateBindDicForm form) {
        log.info("[ShareRelationServiceImpl].[updateRelationDic] ------> 共享用户关系更新 Start, form = {}", JSON.toJSONString(form));
        ShareRelation entity = baseMapper.selectOne(new QueryWrapper<ShareRelation>().lambda().eq(ShareRelation::getUserId, UserUtil.getUserInfo().getId()).eq(ShareRelation::getShareUserId, form.getShareUserId()));
        entity.setRelationDicValue(Integer.valueOf(form.getDicValue()));
        boolean flag = super.update(entity);
        log.info("[ShareRelationServiceImpl].[updateRelationDic] ------> 共享用户关系更新 End, flag = {}", flag);
        return flag;
    }

    /**
     * 写入详情信息
     *
     * @param relDicMap 共享关系字典集合
     * @param dataList  共享用户集合
     */
    private void setDetail(List<ShareUserDTO> dataList, Map<String, Integer> relDicMap) {
        if (!CollectionUtils.isEmpty(dataList)) {
            Map<Integer, DicInfoDTO> dicMap = dicService.getDicMap(DicParentEnum.SHARE_RELATION.getId());
            for (ShareUserDTO shareUser : dataList) {
                if (relDicMap.containsKey(shareUser.getId())) {
                    Integer dicValue = relDicMap.get(shareUser.getId());
                    shareUser.setRelationDicValue(Lists.newArrayList(String.valueOf(dicValue)));
                    if (dicMap.containsKey(dicValue)) {
                        shareUser.setRelationDicName(dicMap.get(dicValue).getDicName());
                    }
                }
            }
        }
    }
}